using System.Security.Cryptography;
using System.Text;

namespace StudentVideo.Utils;

public static class PasswordHasher {

   // 配置参数
   public const int SaltSize = 16;        // 128位盐
   public const int HashSize = 32;        // 256位哈希
   public const int Iterations = 600_000; // PBKDF2迭代次数

   /// <summary>
   /// 生成随机盐
   /// </summary>
   /// <returns></returns>
   public static byte[] GenerateSalt() {
      var salt = new byte[SaltSize];
      using var rng = RandomNumberGenerator.Create();
      rng.GetBytes(salt);

      return salt;
   }

   /// <summary>
   /// 计算密码哈希
   /// </summary>
   /// <param name="password"></param>
   /// <param name="salt"></param>
   /// <returns></returns>
   public static string HashPassword(string password, byte[] salt) {
      var hash = Rfc2898DeriveBytes.Pbkdf2(
         Encoding.UTF8.GetBytes(password), // 明确编码
         salt,
         Iterations,
         HashAlgorithmName.SHA512, // 使用更安全的SHA512
         HashSize
      );

      return Convert.ToBase64String(hash);
   }

   /// <summary>
   /// 生成加密密码和盐
   /// </summary>
   /// <param name="password">密码</param>
   /// <returns></returns>
   public static (string, byte[]) HashPassword(string password) {
      var salt = GenerateSalt();

      var pwd = HashPassword(password, salt);

      return (pwd, salt);
   }

   /// <summary>
   /// 验证密码
   /// </summary>
   /// <param name="password">当前输入的密码</param>
   /// <param name="salt">盐</param>
   /// <param name="storedHash">加密密码</param>
   /// <returns></returns>
   public static bool VerifyPassword(string password, byte[] salt, string storedHash) {
      var computedHash = Rfc2898DeriveBytes.Pbkdf2(
         Encoding.UTF8.GetBytes(password),
         salt,
         Iterations,
         HashAlgorithmName.SHA512,
         HashSize
      );

      var storedHashBytes = Convert.FromBase64String(storedHash);
      return CryptographicOperations.FixedTimeEquals(computedHash, storedHashBytes);
   }
}
